-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
use privileged client in registry instead of user client when getting or creating signatures #16353
use privileged client in registry instead of user client when getting or creating signatures #16353
Conversation
👍 |
/cc @giuseppe |
fa7a498
to
afef3f6
Compare
@csrwng i was wrong, this should imagestreamimage and not imagesignatures (imagesignatures does not have 'get' method, just create and delete), registry reads the signatures by querying the imagestreamimage |
(for the record we need this fix in 3.7, but I see it's alpha so this should go in anyway /cc @mrunalp) |
I can confirm that this worked for me on a test cri-o cluster. |
@liggitt || @enj the registry has an signature endpoint that you can use to get signature... this endpoint is proxying the signature data from openshift (signatures are stored in openshift images...). I believe that granting the image-puller ability to get the imagestreamimage to serve the signature content is fine, but want to double-check if you can think of any security implications. This is the client call: https://github.com/openshift/origin/blob/master/pkg/dockerregistry/server/signaturedispatcher.go#L156 |
@@ -533,6 +533,8 @@ func GetOpenshiftBootstrapClusterRoles() []rbac.ClusterRole { | |||
Rules: []rbac.PolicyRule{ | |||
// pull images | |||
rbac.NewRule("get").Groups(imageGroup, legacyImageGroup).Resources("imagestreams/layers").RuleOrDie(), | |||
// read signatures |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you could just add "imagestreamimages" to the resources in the rule above this one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wanted to make it clear why that rule is there
Er so what is preventing us from using that?
So what extra things can image-puller see/do with this permission? I see that it can get the entire image, and not just the signatures. I just do not have enough context to say how much extra information you are leaking to get access to the signature data. @openshift/sig-security |
@@ -533,6 +533,8 @@ func GetOpenshiftBootstrapClusterRoles() []rbac.ClusterRole { | |||
Rules: []rbac.PolicyRule{ | |||
// pull images | |||
rbac.NewRule("get").Groups(imageGroup, legacyImageGroup).Resources("imagestreams/layers").RuleOrDie(), | |||
// read signatures | |||
rbac.NewRule("get").Groups(imageGroup, legacyImageGroup).Resources("imagestreamimages").RuleOrDie(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this role is intended to grant permissions to call the registry endpoints. the registry is already authorizing getting signatures based on get imagestreams/layers
, have the registry's signature endpoint get signatures from the API using the registry's client, not the user's
afef3f6
to
6d82a66
Compare
@liggitt tested locally and it is working (it returns empty signatures) |
client, ok := userClientFrom(s.ctx) | ||
if !ok { | ||
s.handleError(s.ctx, errcode.ErrorCodeUnknown.WithDetail("unable to get origin client"), w) | ||
client, err := RegistryClientFrom(s.ctx).Client() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
before we let the user create signatures via the registry, verifyImageSignatureAccess ensures they have create imagesignatures
permission, so using the user client here would work. I'm not actually sure whether the registry has create imagesignatures
permission by default
client, ok := userClientFrom(s.ctx) | ||
if !ok { | ||
s.handleError(s.ctx, errcode.ErrorCodeUnknown.WithDetail("unable to get origin client"), w) | ||
client, err := RegistryClientFrom(s.ctx).Client() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this looks fine
switching to use the registry client on get looks fine. I'm not sure about the switch for put |
The code in its current state worked for me on cri-o |
/unassign jim-minter |
s.handleError(s.ctx, errcode.ErrorCodeUnknown.WithDetail("unable to get origin client"), w) | ||
client, err := RegistryClientFrom(s.ctx).Client() | ||
if err != nil { | ||
s.handleError(s.ctx, errcode.ErrorCodeUnknown.WithDetail(fmt.Sprintf("unable to get origin client", err)), w) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does the Sprintf miss the formatter?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, good catch, thx
s.handleError(s.ctx, errcode.ErrorCodeUnknown.WithDetail("unable to get origin client"), w) | ||
client, err := RegistryClientFrom(s.ctx).Client() | ||
if err != nil { | ||
s.handleError(s.ctx, errcode.ErrorCodeUnknown.WithDetail(fmt.Sprintf("unable to get origin client", err)), w) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same here
Do we have a test that confirms user's that have no access to adding signtures actually fail to add them ? |
|
pass registryClient to RegisterSignatureHandlers and hold a reference to it in the handler, rather than retrieve it from the context |
@liggitt yeah, already working on that... |
@mfojtik make RegisterSignatureHandler and SignatureDispatcher to be methods of (app *App). That will allow you use app.registryClient in SignatureDispatcher. You can put app.registryClient into signatureHandler. |
@dmage done, unfortunately i have to plumb the unit tests as well... puzzled how they ever worked as the signaturedispatcher use the clientset and not openshift client. |
@mfojtik don't forget to push your changes :) |
@dmage once they compile... |
5606ec5
to
321715b
Compare
@dmage ok, running out of options, but i'm getting signaturedispatcher_test.go:113: unexpected response status: 401 when running the |
sunday pebkac, nvmd. |
321715b
to
f7ec657
Compare
@@ -57,6 +57,8 @@ func TestSignatureGet(t *testing.T) { | |||
t.Fatal(err) | |||
} | |||
|
|||
os.Setenv("OPENSHIFT_DEFAULT_REGISTRY", "localhost:5000") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dmage for some strange reasons this is needed (at least on OSX) otherwise the NewApp() will fail... we should make this a field in openshift middleware config
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you fix this as part of this PR? This is pretty wonky
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mfojtik yes, configuration check is moved to the app constructor. Adding a field in config will introduce yet another one environment variable for this value (we already have DEFAULT_REGISTRY_URL and OPENSHIFT_DEFAULT_REGISTRY). But I like this idea.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed in a separate commit
@@ -74,6 +78,11 @@ func newRepositoryConfig(ctx context.Context, options map[string]interface{}) (r | |||
} else { | |||
context.GetLogger(ctx).Infof("DEPRECATED: %q is deprecated, use the %q instead", DockerRegistryURLEnvVar, OpenShiftDefaultRegistryEnvVar) | |||
} | |||
rc.registryAddr, err = getStringOption(DockerRegistryURLEnvVarOption, "dockerregistryurl", rc.registryAddr, options) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only if rc.registryAddr has not filled yet.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i would say that having this in configuration file overrides all env vars?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your code erases previous value no matter what. And environment variables usually overrides values in a config file.
@@ -15,6 +15,10 @@ const ( | |||
// DEPRECATED: Use the OPENSHIFT_DEFAULT_REGISTRY instead. | |||
DockerRegistryURLEnvVar = "DOCKER_REGISTRY_URL" | |||
|
|||
// DockerRegistryURLEnvVarOption is an optional environment that overrides the | |||
// DOCKER_REGISTRY_URL. | |||
DockerRegistryURLEnvVarOption = "REGISTRY_MIDDLEWARE_REPOSITORY_OPENSHIFT_DOCKER_REGISTRY_URL" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/DOCKER_REGISTRY_URL/DOCKERREGISTRYURL/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do we need a second envvar for this?
"storage": {{Name: "openshift"}}, | ||
"registry": {{Name: "openshift", Options: configuration.Parameters{"dockerregistryurl": "localhost:5000"}}}, | ||
"repository": {{Name: "openshift", Options: configuration.Parameters{"dockerregistryurl": "localhost:5000"}}}, | ||
"storage": {{Name: "openshift", Options: configuration.Parameters{"dockerregistryurl": "localhost:5000"}}}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this option is only for the repository middleware
c8e0063
to
f8d7d28
Compare
@dmage comments addressed |
/retest |
/lgtm |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: dmage, liggitt, mfojtik The full list of commands accepted by this bot can be found here.
Needs approval from an approver in each of these OWNERS Files:
You can indicate your approval by writing |
Automatic merge from submit-queue (batch tested with PRs 15834, 16321, 16353, 15298, 15433) |
@csrwng
Fixes: #16349